<?php
/*
//------------------------------------------------------------------------------
$mb1 = new Admin_MetaBox(false, 'Plain Metadata', 'plain_metadata.html');

$mb1->addWidget('plain_1');
$mb1->addWidget('plain_2');
$mb1->addWidget('plain_3');

$mb1->priority = Admin_MetaBox::PRIORITY_HIGH;
$mb1->position = Admin_MetaBox::POSITION_SIDE;
//------------------------------------------------------------------------------
plain_metadata.html:

<p>Plain 1: {{ plain_1 }}</p>
<p>Plain 2: {{ plain_2 }}</p>
<p>Plain 3: {{ plain_3 }}</p>
//------------------------------------------------------------------------------
$mb2 = new Admin_MetaBox('complex', 'Complex Metadata', 'complex_metadata.html');

$mb2->addWidget('complex_1');
$mb2->addWidget('complex_2');
$mb2->addWidget('complex_3');

$mb2->priority = Admin_MetaBox::PRIORITY_HIGH;
$mb2->position = Admin_MetaBox::POSITION_SIDE;

Admin_MetaBox::register($mb1);
Admin_MetaBox::register($mb2);
//------------------------------------------------------------------------------
complex_metadata.html:

<p>Complex 1: {{ complex_1 }}</p>
<p>Complex 2: {{ complex_2 }}</p>
<p>Complex 3: {{ complex_3 }}</p>
//------------------------------------------------------------------------------
*/
class Admin_MetaBox
{
  
  const TYPE_PAGE = 'page';
  const TYPE_POST = 'post';
  const TYPE_LINK = 'link';
  
  const POSITION_NORMAL   = 'normal';
  const POSITION_ADVANCED = 'advanced';
  const POSITION_SIDE     = 'side';
  
  const PRIORITY_LOW  = 'low';
  const PRIORITY_HIGH = 'high';
  
  public
    $id,
    $name,
    $title,
    $template,
    $widgets  = array(),
    $type     = self::TYPE_POST,
    $position = self::POSITION_NORMAL,
    $priority = self::PRIORITY_LOW,
    $nonce
    ;
  
  public function __construct($name, $title, $template)
  {
    $this->name     = $name;
    $this->title    = $title;
    $this->template = $template;
    $this->nonce    = array(
      'name'  => get_class($this),
      'value' => wp_create_nonce(get_class($this)),
      );
  }
  
  public static function register($mb)
  {
    add_action('admin_menu', array(&$mb, 'doRegister'));
  }
  
  public function doRegister()
  {
    add_meta_box($this->name ? $this->name : md5(time()), $this->title, array(&$this, 'display'), $this->type, $this->position, $this->priority);
    add_action('save_post', array(&$this, 'save'));
  }
  
  public function getName()
  {
    return $this->name;
  }
  
  public function display($post)
  {
    echo input_hidden_tag($this->nonce['name'], $this->nonce['value']);
    
    if ($this->name)
    {
      $meta = get_post_meta($post->ID, $this->name, true);
      
      if (is_array($meta) && count($meta))
      {
        foreach ((array) $meta as $key => $value)
        {
          if (isset($this->widgets[$key]))
            $this->widgets[$key]->setValue($value);
        }
      }
    }
    else
    {
      foreach ($this->widgets as $key => $widget)
      {
        $meta = get_post_meta($post->ID, $widget->getName(), true);
        if ($meta)
          $this->widgets[$key]->setValue($meta);
      }
    }
    
    $t = Framework::Twig()->loadTemplate($this->template);
    $t->display(array_merge($this->widgets, array('post' => $post)));
  }
  
  public function save($postID)
  {
    if ( !wp_verify_nonce( $_POST[$this->nonce['name']], $this->nonce['name'] )) {
      return $post_id;
    }
    
    if ($this->name)
    {
      $old_meta = get_post_meta($postID, $this->name, true);
      update_post_meta($postID, $this->name, $_POST[$this->name], $old_meta);
    }
    else
    {
      foreach ($this->widgets as $key => $widget)
      {
        $old_meta = get_post_meta($postID, $widget->getName(), true);
        update_post_meta($postID, $widget->getName(), $_POST[$widget->getName()], $old_meta);
      }
    }
    
    return $postID;
  }
  
  public function addWidget($name, $classname = 'Admin_Form_Input', $default_value = null, $options = null, $html_options = null)
  {
    if (class_exists($classname))
    {
      $this->widgets[$name] = new $classname($name, $options, $html_options);
      if ($this->name)
        $this->widgets[$name]->setParent($this);
      if ($default_value)
        $this->widgets[$name]->setValue($default_value);
    }
  }
  
  public function removeWidget($name)
  {
    if (isset($this->widgets[$name]))
      unset($this->widgets[$name]);
  }
}
